package com.example.androidunlockviewdemo.view;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PointF;
import android.util.ArraySet;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

import androidx.annotation.Nullable;

import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

/**
 * @author: smile
 * @date: 2025/9/13 2:46
 * @desc: 描述
 */
public class UnlockView extends View {
    // 默认九宫格图像解锁密码
    private final String DEF_PASSWORD = "2486";

    private boolean unlock = false;

    private Paint mNormalPaint;
    private Paint mSelectedPaint;
    private Paint mPathPaint;

    private float mWidth;
    private float mHeight;

    private float mCircleX;
    private float mCircleY;
    private float mCircleRadius;

    // 储存不被按下的圆
    private List<NumberPoint> mNormalPoints;
    //储存在手指移动后被按下的圆
    private Set<NumberPoint> mSelectedPoints;

    private int mPreSize;

    private Path mPath;
    private int moveFirst;

    //是否绘制路径
    private boolean mHasPath;

    private final int NORMAL = 1;
    private final int MOVE = 3;
    private int mStatus = NORMAL;

    private int mDwonStartX;
    private int mDwonStartY;


    private Set<NumberPoint> mPasswordSet;

    private void init() {
        mNormalPaint = getPaint(Color.parseColor("#f81B60"));
        mSelectedPaint = getPaint(Color.parseColor("#aaaaff"));
        mPathPaint = getPaint(Color.parseColor("#aaaaff"));
        mPathPaint.setStyle(Paint.Style.STROKE);
        mPathPaint.setStrokeWidth(15f);

        mNormalPoints = new ArrayList<>();
        mSelectedPoints = new ArraySet<>();
        mPasswordSet = new LinkedHashSet<>();

        mWidth = getResources().getDisplayMetrics().widthPixels;
        mHeight = getResources().getDisplayMetrics().heightPixels;

        mCircleX = mWidth / 2;
        mCircleY = mHeight / 2;

        mCircleRadius = mCircleX / 5;

        mPath = new Path();
        mPath.setFillType(Path.FillType.EVEN_ODD);
        addNinePoints();// 初始化 9 个点

        setDrawPath(true);
    }

    private Paint getPaint(int color) {
        Paint paint = new Paint();
        paint.setDither(true);
        paint.setAntiAlias(true);
        paint.setTextSize(70f);
        paint.setColor(color);
        return paint;
    }

    public UnlockView(Context context) {
        this(context, null);
    }

    public UnlockView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public UnlockView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    /**
     * 添加 9 个点
     */
    private void addNinePoints() {
        mNormalPoints.clear();
        NumberPoint mPoint = null;

        for (int i = 1; i <= 3; i++) {
            // 第一排 第 1 个点
            float x2 = mCircleX / 3;
            float y = mCircleY / 2 * i;// 每一排 y 坐标都是一个样的
            mPoint = new NumberPoint(1 + (i - 1) * 3);
            mPoint.set(x2, y);
            mNormalPoints.add(mPoint);

            // 第一排 第 2 个点
            float x1 = mCircleX;
            mPoint = new NumberPoint(2 + (i - 1) * 3);
            mPoint.set(x1, y);
            mNormalPoints.add(mPoint);

            // 第一排 第 3 个点
            float x3 = mWidth - mCircleX / 3;
            mPoint = new NumberPoint(3 + (i - 1) * 3);
            mPoint.set(x3, y);
            mNormalPoints.add(mPoint);
        }
    }

    public void setDrawPath(boolean hasPath) {
        this.mHasPath = hasPath;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        switch (mStatus) {
            case NORMAL:
                drawCircles(canvas);

                break;
            case MOVE:
                drawCircles(canvas);

                if (mSelectedPoints.size() > 0) {
                    for (NumberPoint point : mSelectedPoints) {
                        canvas.drawCircle(point.x, point.y, mCircleRadius, mSelectedPaint);

                        mPasswordSet.add(point);
                    }


                    if (mHasPath) {
                        mPath.reset();
                        moveFirst = 0;
                        for (NumberPoint point : mPasswordSet) {
                            if ((++moveFirst) == 1)
                                mPath.moveTo(point.x, point.y);
                            else
                                mPath.lineTo(point.x, point.y);

                        }
                        //如果需要绘制路径
                        canvas.drawPath(mPath, mPathPaint);
                    }
                }
                break;
        }
    }

    private void drawCircles(Canvas canvas) {
        if (unlock) {
            mNormalPaint.setColor(Color.parseColor("#00ff00"));
            canvas.drawText("解锁成功", mWidth / 2 - mNormalPaint.getTextSize() * 2f, mHeight / 9, mNormalPaint);
        } else {
            mNormalPaint.setColor(Color.parseColor("#ff0000"));
            canvas.drawText("请输入解锁图案", mWidth / 2 - mNormalPaint.getTextSize() * 3.5f, mHeight / 9, mNormalPaint);
        }

        for (NumberPoint point : mNormalPoints) {
            canvas.drawCircle(point.x, point.y, mCircleRadius, mNormalPaint);
        }
    }

    @SuppressLint("ClickableViewAccessibility")
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float downX = event.getX();
        float downY = event.getY();
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_MOVE:
                for (NumberPoint point : mNormalPoints) {
                    // 取出每一个圆的圆心坐标
                    unlock = false;
                    mStatus = MOVE;
                    float circleX = point.x;
                    float circleY = point.y;
                    if (isInsideCircle(downX, downY, circleX, circleY)) {
                        mSelectedPoints.add(point);
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
                mStatus = NORMAL;

                StringBuffer password = new StringBuffer();
                for (NumberPoint point : mPasswordSet) {
                    password.append(point.getNumber());
                }

                Log.i("========", "password: " + password);
                if (DEF_PASSWORD.equals(password.toString())) {
                    unlock = true;
                }

                mPasswordSet.clear();
                mSelectedPoints.clear();
                mPath.reset();
                moveFirst = 0;
                break;
        }
        invalidate();
        return true;
    }

    private boolean isInsideCircle(float downX, float downY, float circleX, float circleY) {
        return mCircleRadius > Math.sqrt(Math.pow(downX - circleX, 2) + Math.pow(downY - circleY, 2));
    }


    public class NumberPoint extends PointF {
        private int number;

        public NumberPoint(int number) {
            this.number = number;
        }

        public int getNumber() {
            return number;
        }

    }

}
